{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "kR-4eNdK6lYS"
   },
   "source": [
    "Deep Learning\n",
    "=============\n",
    "\n",
    "Assignment 3\n",
    "------------\n",
    "\n",
    "Previously in `2_fullyconnected.ipynb`, you trained a logistic regression and a neural network model.\n",
    "\n",
    "The goal of this assignment is to explore regularization techniques."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "JLpLa8Jt7Vu4"
   },
   "outputs": [],
   "source": [
    "# These are all the modules we'll be using later. Make sure you can import them\n",
    "# before proceeding further.\n",
    "from __future__ import print_function\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from six.moves import cPickle as pickle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "1HrCK6e17WzV"
   },
   "source": [
    "First reload the data we generated in _notmist.ipynb_."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 11777,
     "status": "ok",
     "timestamp": 1449849322348,
     "user": {
      "color": "",
      "displayName": "",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "",
      "photoUrl": "",
      "sessionId": "0",
      "userId": ""
     },
     "user_tz": 480
    },
    "id": "y3-cj1bpmuxc",
    "outputId": "e03576f1-ebbe-4838-c388-f1777bcc9873"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (200000, 28, 28) (200000,)\n",
      "Validation set (10000, 28, 28) (10000,)\n",
      "Test set (10000, 28, 28) (10000,)\n"
     ]
    }
   ],
   "source": [
    "pickle_file = 'notMNIST.pickle'\n",
    "\n",
    "with open(pickle_file, 'rb') as f:\n",
    "    save = pickle.load(f)\n",
    "    train_dataset = save['train_dataset']\n",
    "    train_labels = save['train_labels']\n",
    "    valid_dataset = save['valid_dataset']\n",
    "    valid_labels = save['valid_labels']\n",
    "    test_dataset = save['test_dataset']\n",
    "    test_labels = save['test_labels']\n",
    "    del save  # hint to help gc free up memory\n",
    "    print('Training set', train_dataset.shape, train_labels.shape)\n",
    "    print('Validation set', valid_dataset.shape, valid_labels.shape)\n",
    "    print('Test set', test_dataset.shape, test_labels.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "L7aHrm6nGDMB"
   },
   "source": [
    "Reformat into a shape that's more adapted to the models we're going to train:\n",
    "- data as a flat matrix,\n",
    "- labels as float 1-hot encodings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 11728,
     "status": "ok",
     "timestamp": 1449849322356,
     "user": {
      "color": "",
      "displayName": "",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "",
      "photoUrl": "",
      "sessionId": "0",
      "userId": ""
     },
     "user_tz": 480
    },
    "id": "IRSyYiIIGIzS",
    "outputId": "3f8996ee-3574-4f44-c953-5c8a04636582"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (200000, 784) (200000, 10)\n",
      "Validation set (10000, 784) (10000, 10)\n",
      "Test set (10000, 784) (10000, 10)\n"
     ]
    }
   ],
   "source": [
    "image_size = 28\n",
    "num_labels = 10\n",
    "\n",
    "def reformat(dataset, labels):\n",
    "    dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32)\n",
    "    # Map 2 to [0.0, 1.0, 0.0 ...], 3 to [0.0, 0.0, 1.0 ...]\n",
    "    labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)\n",
    "    return dataset, labels\n",
    "train_dataset, train_labels = reformat(train_dataset, train_labels)\n",
    "valid_dataset, valid_labels = reformat(valid_dataset, valid_labels)\n",
    "test_dataset, test_labels = reformat(test_dataset, test_labels)\n",
    "print('Training set', train_dataset.shape, train_labels.shape)\n",
    "print('Validation set', valid_dataset.shape, valid_labels.shape)\n",
    "print('Test set', test_dataset.shape, test_labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "RajPLaL_ZW6w"
   },
   "outputs": [],
   "source": [
    "def accuracy(predictions, labels):\n",
    "    return (100.0 * np.sum(np.argmax(predictions, 1) == np.argmax(labels, 1)) / predictions.shape[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "sgLbUAQ1CW-1"
   },
   "source": [
    "---\n",
    "Problem 1\n",
    "---------\n",
    "\n",
    "Introduce and tune L2 regularization for both logistic and neural network models. Remember that L2 amounts to adding a penalty on the norm of the weights to the loss. In TensorFlow, you can compute the L2 loss for a tensor `t` using `nn.l2_loss(t)`. The right amount of regularization should improve your validation / test accuracy.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3 align='Left'>Logistic</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    beta_regul = tf.placeholder(tf.float32)\n",
    "    \n",
    "    # Variables.\n",
    "    weights = tf.Variable(\n",
    "    tf.truncated_normal([image_size * image_size, num_labels]))\n",
    "    biases = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    logits = tf.matmul(tf_train_dataset, weights) + biases\n",
    "    loss = tf.reduce_mean(\n",
    "    tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels)) + beta_regul * tf.nn.l2_loss(weights)\n",
    "  \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    valid_prediction = tf.nn.softmax(\n",
    "    tf.matmul(tf_valid_dataset, weights) + biases)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(tf_test_dataset, weights) + biases)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 18.604839\n",
      "Minibatch accuracy: 10.2%\n",
      "Validation accuracy: 13.5%\n",
      "Minibatch loss at step 500: 3.377822\n",
      "Minibatch accuracy: 71.1%\n",
      "Validation accuracy: 75.9%\n",
      "Minibatch loss at step 1000: 1.723570\n",
      "Minibatch accuracy: 78.9%\n",
      "Validation accuracy: 78.5%\n",
      "Minibatch loss at step 1500: 1.384084\n",
      "Minibatch accuracy: 78.9%\n",
      "Validation accuracy: 80.2%\n",
      "Minibatch loss at step 2000: 1.082147\n",
      "Minibatch accuracy: 81.2%\n",
      "Validation accuracy: 79.6%\n",
      "Minibatch loss at step 2500: 1.023130\n",
      "Minibatch accuracy: 76.6%\n",
      "Validation accuracy: 81.6%\n",
      "Minibatch loss at step 3000: 0.725348\n",
      "Minibatch accuracy: 80.5%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 3500: 0.596389\n",
      "Minibatch accuracy: 87.5%\n",
      "Validation accuracy: 81.8%\n",
      "Minibatch loss at step 4000: 0.865103\n",
      "Minibatch accuracy: 78.9%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 4500: 0.595295\n",
      "Minibatch accuracy: 84.4%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 5000: 0.533092\n",
      "Minibatch accuracy: 85.2%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 5500: 0.970525\n",
      "Minibatch accuracy: 72.7%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 6000: 0.723037\n",
      "Minibatch accuracy: 76.6%\n",
      "Validation accuracy: 81.9%\n",
      "Minibatch loss at step 6500: 1.030621\n",
      "Minibatch accuracy: 75.8%\n",
      "Validation accuracy: 81.2%\n",
      "Minibatch loss at step 7000: 0.719776\n",
      "Minibatch accuracy: 78.9%\n",
      "Validation accuracy: 82.5%\n",
      "Minibatch loss at step 7500: 0.715401\n",
      "Minibatch accuracy: 82.8%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 8000: 0.609973\n",
      "Minibatch accuracy: 84.4%\n",
      "Validation accuracy: 82.2%\n",
      "Minibatch loss at step 8500: 0.668251\n",
      "Minibatch accuracy: 82.0%\n",
      "Validation accuracy: 81.7%\n",
      "Minibatch loss at step 9000: 0.551616\n",
      "Minibatch accuracy: 85.9%\n",
      "Validation accuracy: 82.1%\n",
      "Minibatch loss at step 9500: 0.804506\n",
      "Minibatch accuracy: 76.6%\n",
      "Validation accuracy: 81.4%\n",
      "Test accuracy: 88.5%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 10000\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, beta_regul : 1e-3}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 500 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3 align='Left'>1 Layer Neural Network</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes = 1024\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    beta_regul = tf.placeholder(tf.float32)\n",
    "  \n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(tf.truncated_normal([image_size * image_size, num_hidden_nodes]))\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes]))\n",
    "    weights2 = tf.Variable(tf.truncated_normal([num_hidden_nodes, num_labels]))\n",
    "    biases2 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    logits = tf.matmul(lay1_train, weights2) + biases2\n",
    "    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels)) + \\\n",
    "      beta_regul * (tf.nn.l2_loss(weights1) + tf.nn.l2_loss(weights2))\n",
    "  \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay1_test, weights2) + biases2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 605.301636\n",
      "Minibatch accuracy: 11.7%\n",
      "Validation accuracy: 20.9%\n",
      "Minibatch loss at step 500: 196.777649\n",
      "Minibatch accuracy: 72.7%\n",
      "Validation accuracy: 81.0%\n",
      "Minibatch loss at step 1000: 114.369263\n",
      "Minibatch accuracy: 78.1%\n",
      "Validation accuracy: 81.1%\n",
      "Minibatch loss at step 1500: 68.932152\n",
      "Minibatch accuracy: 78.9%\n",
      "Validation accuracy: 83.2%\n",
      "Minibatch loss at step 2000: 41.586166\n",
      "Minibatch accuracy: 83.6%\n",
      "Validation accuracy: 85.2%\n",
      "Minibatch loss at step 2500: 25.518885\n",
      "Minibatch accuracy: 83.6%\n",
      "Validation accuracy: 86.4%\n",
      "Minibatch loss at step 3000: 15.410585\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 87.1%\n",
      "Minibatch loss at step 3500: 9.543892\n",
      "Minibatch accuracy: 89.1%\n",
      "Validation accuracy: 87.9%\n",
      "Minibatch loss at step 4000: 6.184585\n",
      "Minibatch accuracy: 84.4%\n",
      "Validation accuracy: 88.2%\n",
      "Minibatch loss at step 4500: 3.711422\n",
      "Minibatch accuracy: 93.8%\n",
      "Validation accuracy: 88.3%\n",
      "Minibatch loss at step 5000: 2.439088\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 88.5%\n",
      "Minibatch loss at step 5500: 1.904946\n",
      "Minibatch accuracy: 83.6%\n",
      "Validation accuracy: 88.4%\n",
      "Minibatch loss at step 6000: 1.224182\n",
      "Minibatch accuracy: 90.6%\n",
      "Validation accuracy: 88.2%\n",
      "Minibatch loss at step 6500: 1.120467\n",
      "Minibatch accuracy: 83.6%\n",
      "Validation accuracy: 88.2%\n",
      "Minibatch loss at step 7000: 0.788844\n",
      "Minibatch accuracy: 89.8%\n",
      "Validation accuracy: 88.5%\n",
      "Minibatch loss at step 7500: 0.673431\n",
      "Minibatch accuracy: 90.6%\n",
      "Validation accuracy: 88.9%\n",
      "Minibatch loss at step 8000: 0.509613\n",
      "Minibatch accuracy: 93.0%\n",
      "Validation accuracy: 88.6%\n",
      "Minibatch loss at step 8500: 0.518794\n",
      "Minibatch accuracy: 90.6%\n",
      "Validation accuracy: 88.7%\n",
      "Minibatch loss at step 9000: 0.466654\n",
      "Minibatch accuracy: 89.1%\n",
      "Validation accuracy: 88.1%\n",
      "Minibatch loss at step 9500: 0.592488\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 88.3%\n",
      "Test accuracy: 94.5%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 10000\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, beta_regul : 1e-3}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 500 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "na8xX2yHZzNF"
   },
   "source": [
    "---\n",
    "Problem 2\n",
    "---------\n",
    "Let's demonstrate an extreme case of overfitting. Restrict your training data to just a few batches. What happens?\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes = 1024\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    beta_regul = tf.placeholder(tf.float32)\n",
    "  \n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(tf.truncated_normal([image_size * image_size, num_hidden_nodes]))\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes]))\n",
    "    weights2 = tf.Variable(tf.truncated_normal([num_hidden_nodes, num_labels]))\n",
    "    biases2 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    logits = tf.matmul(lay1_train, weights2) + biases2\n",
    "    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))\n",
    "  \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay1_test, weights2) + biases2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 485.404602\n",
      "Minibatch accuracy: 8.6%\n",
      "Validation accuracy: 31.6%\n",
      "Minibatch loss at step 2: 1037.384277\n",
      "Minibatch accuracy: 46.9%\n",
      "Validation accuracy: 44.5%\n",
      "Minibatch loss at step 4: 238.918762\n",
      "Minibatch accuracy: 73.4%\n",
      "Validation accuracy: 46.3%\n",
      "Minibatch loss at step 6: 55.773361\n",
      "Minibatch accuracy: 90.6%\n",
      "Validation accuracy: 58.1%\n",
      "Minibatch loss at step 8: 17.550159\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 58.9%\n",
      "Minibatch loss at step 10: 6.202036\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 59.5%\n",
      "Minibatch loss at step 12: 0.988351\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 14: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 16: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 18: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 20: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 22: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 24: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 26: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 28: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 30: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 32: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 34: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 36: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 38: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 40: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 42: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 44: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 46: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 48: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 50: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 52: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 54: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 56: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 58: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 60: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 62: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 64: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 66: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 68: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 70: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 72: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 74: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 76: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 78: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 80: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 82: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 84: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 86: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 88: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 90: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 92: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 94: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 96: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 98: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Minibatch loss at step 100: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 59.6%\n",
      "Test accuracy: 65.2%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 101\n",
    "num_batches = 2\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        #offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        offset = step % num_batches\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, beta_regul : 1e-3}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 2 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(\n",
    "            valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since there are far too much parameters and no regularization, the accuracy of the batches is 100%. The generalization capability is poor, as shown in the validation and test accuracy."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ww3SCBUdlkRc"
   },
   "source": [
    "---\n",
    "Problem 3\n",
    "---------\n",
    "Introduce Dropout on the hidden layer of the neural network. Remember: Dropout should only be introduced during training, not evaluation, otherwise your evaluation results would be stochastic as well. TensorFlow provides `nn.dropout()` for that, but you have to make sure it's only inserted during training.\n",
    "\n",
    "What happens to our extreme overfitting case?\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes = 1024\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "  \n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(tf.truncated_normal([image_size * image_size, num_hidden_nodes]))\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes]))\n",
    "    weights2 = tf.Variable(tf.truncated_normal([num_hidden_nodes, num_labels]))\n",
    "    biases2 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    drop1 = tf.nn.dropout(lay1_train, 0.5)\n",
    "    logits = tf.matmul(drop1, weights2) + biases2\n",
    "    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))\n",
    "    \n",
    "    # Optimizer.\n",
    "    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay1_test, weights2) + biases2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 508.075623\n",
      "Minibatch accuracy: 11.7%\n",
      "Validation accuracy: 29.4%\n",
      "Minibatch loss at step 2: 797.276001\n",
      "Minibatch accuracy: 50.8%\n",
      "Validation accuracy: 31.7%\n",
      "Minibatch loss at step 4: 414.272583\n",
      "Minibatch accuracy: 68.8%\n",
      "Validation accuracy: 53.8%\n",
      "Minibatch loss at step 6: 16.948627\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 64.9%\n",
      "Minibatch loss at step 8: 3.570223\n",
      "Minibatch accuracy: 95.3%\n",
      "Validation accuracy: 62.5%\n",
      "Minibatch loss at step 10: 2.049491\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 64.4%\n",
      "Minibatch loss at step 12: 1.677652\n",
      "Minibatch accuracy: 97.7%\n",
      "Validation accuracy: 64.1%\n",
      "Minibatch loss at step 14: 5.430785\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 66.1%\n",
      "Minibatch loss at step 16: 4.851165\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 64.8%\n",
      "Minibatch loss at step 18: 3.324074\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 65.0%\n",
      "Minibatch loss at step 20: 2.398253\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 22: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.4%\n",
      "Minibatch loss at step 24: 2.323184\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 66.0%\n",
      "Minibatch loss at step 26: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.1%\n",
      "Minibatch loss at step 28: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.1%\n",
      "Minibatch loss at step 30: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.0%\n",
      "Minibatch loss at step 32: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.0%\n",
      "Minibatch loss at step 34: 0.665471\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 36: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.1%\n",
      "Minibatch loss at step 38: 1.233972\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 65.5%\n",
      "Minibatch loss at step 40: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.0%\n",
      "Minibatch loss at step 42: 0.684885\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 65.9%\n",
      "Minibatch loss at step 44: 1.067188\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 65.9%\n",
      "Minibatch loss at step 46: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.9%\n",
      "Minibatch loss at step 48: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.5%\n",
      "Minibatch loss at step 50: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.5%\n",
      "Minibatch loss at step 52: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.4%\n",
      "Minibatch loss at step 54: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.1%\n",
      "Minibatch loss at step 56: 0.576552\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.1%\n",
      "Minibatch loss at step 58: 0.874456\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 65.7%\n",
      "Minibatch loss at step 60: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 65.7%\n",
      "Minibatch loss at step 62: 1.001337\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 65.3%\n",
      "Minibatch loss at step 64: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.6%\n",
      "Minibatch loss at step 66: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.6%\n",
      "Minibatch loss at step 68: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.6%\n",
      "Minibatch loss at step 70: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.6%\n",
      "Minibatch loss at step 72: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.6%\n",
      "Minibatch loss at step 74: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.6%\n",
      "Minibatch loss at step 76: 0.398481\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.9%\n",
      "Minibatch loss at step 78: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 64.4%\n",
      "Minibatch loss at step 80: 1.423306\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 82: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 84: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 86: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 66.5%\n",
      "Minibatch loss at step 88: 1.079943\n",
      "Minibatch accuracy: 98.4%\n",
      "Validation accuracy: 67.7%\n",
      "Minibatch loss at step 90: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.7%\n",
      "Minibatch loss at step 92: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.7%\n",
      "Minibatch loss at step 94: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.6%\n",
      "Minibatch loss at step 96: 1.007961\n",
      "Minibatch accuracy: 99.2%\n",
      "Validation accuracy: 67.3%\n",
      "Minibatch loss at step 98: 0.000000\n",
      "Minibatch accuracy: 100.0%\n",
      "Validation accuracy: 67.3%\n",
      "Test accuracy: 74.7%\n"
     ]
    }
   ],
   "source": [
    "num_steps = 100\n",
    "num_batches = 2\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        #offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        offset = step % num_batches\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 2 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dropout definitely helped, but it is far better to use regularization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "-b1hTz3VWZjw"
   },
   "source": [
    "---\n",
    "Problem 4\n",
    "---------\n",
    "\n",
    "Try to get the best performance you can using a multi-layer model! The best reported test accuracy using a deep network is [97.1%](http://yaroslavvb.blogspot.com/2011/09/notmnist-dataset.html?showComment=1391023266211#c8758720086795711595).\n",
    "\n",
    "One avenue you can explore is to add multiple layers.\n",
    "\n",
    "Another one is to use learning rate decay:\n",
    "\n",
    "    global_step = tf.Variable(0)  # count the number of steps taken.\n",
    "    learning_rate = tf.train.exponential_decay(0.5, global_step, ...)\n",
    "    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)\n",
    " \n",
    " ---\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "num_hidden_nodes1 = 1024\n",
    "num_hidden_nodes2 = 256\n",
    "num_hidden_nodes3 = 128\n",
    "keep_prob = 0.5\n",
    "\n",
    "graph = tf.Graph()\n",
    "with graph.as_default():\n",
    "\n",
    "    # Input data. For the training data, we use a placeholder that will be fed\n",
    "    # at run time with a training minibatch.\n",
    "    tf_train_dataset = tf.placeholder(tf.float32,\n",
    "                                    shape=(batch_size, image_size * image_size))\n",
    "    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))\n",
    "    tf_valid_dataset = tf.constant(valid_dataset)\n",
    "    tf_test_dataset = tf.constant(test_dataset)\n",
    "    global_step = tf.Variable(0)\n",
    "\n",
    "    # Variables.\n",
    "    weights1 = tf.Variable(\n",
    "    tf.truncated_normal(\n",
    "        [image_size * image_size, num_hidden_nodes1],\n",
    "        stddev=np.sqrt(2.0 / (image_size * image_size)))\n",
    "    )\n",
    "    biases1 = tf.Variable(tf.zeros([num_hidden_nodes1]))\n",
    "    weights2 = tf.Variable(\n",
    "    tf.truncated_normal([num_hidden_nodes1, num_hidden_nodes2], stddev=np.sqrt(2.0 / num_hidden_nodes1)))\n",
    "    biases2 = tf.Variable(tf.zeros([num_hidden_nodes2]))\n",
    "    weights3 = tf.Variable(tf.truncated_normal([num_hidden_nodes2, num_hidden_nodes3], stddev=np.sqrt(2.0 / num_hidden_nodes2)))\n",
    "    biases3 = tf.Variable(tf.zeros([num_hidden_nodes3]))\n",
    "    weights4 = tf.Variable(\n",
    "    tf.truncated_normal([num_hidden_nodes3, num_labels], stddev=np.sqrt(2.0 / num_hidden_nodes3)))\n",
    "    biases4 = tf.Variable(tf.zeros([num_labels]))\n",
    "  \n",
    "    # Training computation.\n",
    "    lay1_train = tf.nn.relu(tf.matmul(tf_train_dataset, weights1) + biases1)\n",
    "    lay2_train = tf.nn.relu(tf.matmul(lay1_train, weights2) + biases2)\n",
    "    lay3_train = tf.nn.relu(tf.matmul(lay2_train, weights3) + biases3)\n",
    "    logits = tf.matmul(lay3_train, weights4) + biases4\n",
    "    loss = tf.reduce_mean(\n",
    "    tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels))\n",
    "  \n",
    "    # Optimizer.\n",
    "    learning_rate = tf.train.exponential_decay(0.5, global_step, 4000, 0.65, staircase=True)\n",
    "    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)\n",
    "  \n",
    "    # Predictions for the training, validation, and test data.\n",
    "    train_prediction = tf.nn.softmax(logits)\n",
    "    lay1_valid = tf.nn.relu(tf.matmul(tf_valid_dataset, weights1) + biases1)\n",
    "    lay2_valid = tf.nn.relu(tf.matmul(lay1_valid, weights2) + biases2)\n",
    "    lay3_valid = tf.nn.relu(tf.matmul(lay2_valid, weights3) + biases3)\n",
    "    valid_prediction = tf.nn.softmax(tf.matmul(lay3_valid, weights4) + biases4)\n",
    "    lay1_test = tf.nn.relu(tf.matmul(tf_test_dataset, weights1) + biases1)\n",
    "    lay2_test = tf.nn.relu(tf.matmul(lay1_test, weights2) + biases2)\n",
    "    lay3_test = tf.nn.relu(tf.matmul(lay2_test, weights3) + biases3)\n",
    "    test_prediction = tf.nn.softmax(tf.matmul(lay3_test, weights4) + biases4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialized\n",
      "Minibatch loss at step 0: 2.394002\n",
      "Minibatch accuracy: 10.2%\n",
      "Validation accuracy: 33.6%\n",
      "Minibatch loss at step 500: 0.569041\n",
      "Minibatch accuracy: 78.1%\n",
      "Validation accuracy: 85.0%\n",
      "Minibatch loss at step 1000: 0.365728\n",
      "Minibatch accuracy: 87.5%\n",
      "Validation accuracy: 88.0%\n",
      "Minibatch loss at step 1500: 0.431339\n",
      "Minibatch accuracy: 86.7%\n",
      "Validation accuracy: 88.4%\n",
      "Minibatch loss at step 2000: 0.361003\n",
      "Minibatch accuracy: 88.3%\n",
      "Validation accuracy: 88.9%\n",
      "Minibatch loss at step 2500: 0.400798\n",
      "Minibatch accuracy: 86.7%\n",
      "Validation accuracy: 89.1%\n",
      "Minibatch loss at step 3000: 0.251090\n",
      "Minibatch accuracy: 90.6%\n",
      "Validation accuracy: 89.5%\n",
      "Minibatch loss at step 3500: 0.226094\n",
      "Minibatch accuracy: 93.8%\n",
      "Validation accuracy: 89.2%\n",
      "Minibatch loss at step 4000: 0.429406\n",
      "Minibatch accuracy: 86.7%\n",
      "Validation accuracy: 89.7%\n",
      "Minibatch loss at step 4500: 0.145540\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 90.5%\n",
      "Minibatch loss at step 5000: 0.190444\n",
      "Minibatch accuracy: 94.5%\n",
      "Validation accuracy: 90.3%\n",
      "Minibatch loss at step 5500: 0.301969\n",
      "Minibatch accuracy: 89.1%\n",
      "Validation accuracy: 90.4%\n",
      "Minibatch loss at step 6000: 0.155946\n",
      "Minibatch accuracy: 95.3%\n",
      "Validation accuracy: 90.5%\n",
      "Minibatch loss at step 6500: 0.301091\n",
      "Minibatch accuracy: 89.8%\n",
      "Validation accuracy: 90.7%\n",
      "Minibatch loss at step 7000: 0.199711\n",
      "Minibatch accuracy: 92.2%\n",
      "Validation accuracy: 90.3%\n",
      "Minibatch loss at step 7500: 0.178089\n",
      "Minibatch accuracy: 94.5%\n",
      "Validation accuracy: 90.4%\n",
      "Minibatch loss at step 8000: 0.086366\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 89.9%\n",
      "Minibatch loss at step 8500: 0.163761\n",
      "Minibatch accuracy: 96.1%\n",
      "Validation accuracy: 90.9%\n",
      "Minibatch loss at step 9000: 0.142373\n",
      "Minibatch accuracy: 96.9%\n",
      "Validation accuracy: 91.2%\n",
      "Minibatch loss at step 9500: 0.137270\n",
      "Minibatch accuracy: 95.3%\n",
      "Validation accuracy: 91.1%\n",
      "Minibatch loss at step 10000: 0.153941\n",
      "Minibatch accuracy: 94.5%\n",
      "Validation accuracy: 90.8%\n",
      "Test accuracy: 95.9%\n"
     ]
    }
   ],
   "source": [
    "# 10000 steps is more than enough\n",
    "\n",
    "num_steps = 10001\n",
    "\n",
    "with tf.Session(graph=graph) as session:\n",
    "    tf.initialize_all_variables().run()\n",
    "    print(\"Initialized\")\n",
    "    for step in range(num_steps):\n",
    "        # Pick an offset within the training data, which has been randomized.\n",
    "        # Note: we could use better randomization across epochs.\n",
    "        offset = (step * batch_size) % (train_labels.shape[0] - batch_size)\n",
    "        # Generate a minibatch.\n",
    "        batch_data = train_dataset[offset:(offset + batch_size), :]\n",
    "        batch_labels = train_labels[offset:(offset + batch_size), :]\n",
    "        # Prepare a dictionary telling the session where to feed the minibatch.\n",
    "        # The key of the dictionary is the placeholder node of the graph to be fed,\n",
    "        # and the value is the numpy array to feed to it.\n",
    "        feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}\n",
    "        _, l, predictions = session.run(\n",
    "          [optimizer, loss, train_prediction], feed_dict=feed_dict)\n",
    "        if (step % 500 == 0):\n",
    "            print(\"Minibatch loss at step %d: %f\" % (step, l))\n",
    "            print(\"Minibatch accuracy: %.1f%%\" % accuracy(predictions, batch_labels))\n",
    "            print(\"Validation accuracy: %.1f%%\" % accuracy(valid_prediction.eval(), valid_labels))\n",
    "    print(\"Test accuracy: %.1f%%\" % accuracy(test_prediction.eval(), test_labels))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "default_view": {},
   "name": "3_regularization.ipynb",
   "provenance": [],
   "version": "0.3.2",
   "views": {}
  },
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
